home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / ip / slip / cslip-2.6 / sunos3 / net / if_sl.c next >
Encoding:
C/C++ Source or Header  |  1992-07-25  |  24.6 KB  |  986 lines

  1. /*
  2.  * Copyright (c) 1989, 1990, 1991 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that the above copyright notice and this paragraph are
  7.  * duplicated in all such forms and that any documentation,
  8.  * advertising materials, and other materials related to such
  9.  * distribution and use acknowledge that the software was developed
  10.  * by the University of California, Berkeley.  The name of the
  11.  * University may not be used to endorse or promote products derived
  12.  * from this software without specific prior written permission.
  13.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  14.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  15.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16.  */
  17. #ifndef lint
  18. static char rcsid[] =
  19.     "@(#) $Header: if_sl.c,v 1.18 92/07/25 22:39:24 leres Exp $ (LBL)";
  20. #endif
  21.  
  22. /*
  23.  * Serial Line interface
  24.  *
  25.  * Originally written by
  26.  *     Rick Adams
  27.  *     Center for Seismic Studies
  28.  *     1300 N 17th Street, Suite 1450
  29.  *     Arlington, Virginia 22209
  30.  *     (703)276-7900
  31.  *     rick@seismo.css.gov
  32.  *     seismo!rick
  33.  *
  34.  * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris).
  35.  * N.B.: this belongs in netinet, not net, the way it stands now.
  36.  * Should have a link-layer type designation, but wouldn't be
  37.  * backwards-compatible.
  38.  *
  39.  * Converted to 4.3BSD Beta by Chris Torek.
  40.  * Other changes made at Berkeley, based in part on code by Kirk Smith.
  41.  *
  42.  * Hacked almost beyond recognition by Van Jacobson (van@helios.ee.lbl.gov).
  43.  * Added priority queuing for "interactive" traffic; hooks for TCP
  44.  * header compression; ICMP filtering (at 2400 baud, some cretin
  45.  * pinging you can use up all your bandwidth); conditionals for Sun
  46.  * OS 3.x in addition to 4.x BSD.  Made low clist behavior more robust
  47.  * and slightly less likely to hang serial line.  Sped up a bunch of
  48.  * things.
  49.  */
  50.  
  51. /* originally from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
  52.  
  53. #include "sl.h"
  54. #if NSL > 0
  55. #ifndef LBL
  56. #define LBL
  57. #endif
  58.  
  59. #include "param.h"
  60. #include "mbuf.h"
  61. #include "buf.h"
  62. #include "dk.h"
  63. #include "socket.h"
  64. #include "ioctl.h"
  65. #include "file.h"
  66. #include "tty.h"
  67. #include "errno.h"
  68.  
  69. #include "if.h"
  70. #include "netisr.h"
  71. #include "route.h"
  72. #if INET
  73. #include "../netinet/in.h"
  74. #include "../netinet/in_systm.h"
  75. #ifndef sun
  76. #include "../netinet/in_var.h"
  77. #include "../netinet/ip.h"
  78. #else
  79. #include "../netinet/ip.h"
  80. #include "../netinet/ip_var.h"
  81. #include "protosw.h"
  82. #endif
  83. #endif
  84.  
  85. #ifndef sun
  86. #include "machine/mtpr.h"
  87. #endif
  88.  
  89. #include "slcompress.h"
  90. #include "if_slvar.h"
  91. #include "slip.h"
  92.  
  93. #include "bpfilter.h"
  94. #if NBPFILTER > 0
  95. #include <sys/time.h>
  96. #include <net/bpf.h>
  97. #endif
  98.  
  99. /*
  100.  * The following are patchable defaults for the three options
  101.  * in the interface flags word.  If desired, they should be set
  102.  * by config file options SL_DOCOMPRESS, SL_ALLOWCOMPRESS and
  103.  * SL_NOICMP.
  104.  *
  105.  *   sl_docompress    If = 1, compression for a line will default to "on"
  106.  *
  107.  *   sl_allowcompres    If = 1, compression for a line will default to "off"
  108.  *            but will be turned on if a compressed packet is
  109.  *            received. 
  110.  *
  111.  *   sl_noicmp        If = 1, outbound ICMP packets will be discarded.
  112.  *            XXX - shouldn't have to set this but some cretin
  113.  *            pinging us can drive our throughput to zero (not
  114.  *            to mention the raft of quenches we'll get if we're
  115.  *            unlucky enough to have to traverse the milnet.
  116.  */
  117. #ifndef SL_DOCOMPRESS
  118. #define SL_DOCOMPRESS 0
  119. #endif
  120. #ifndef SL_ALLOWCOMPRESS
  121. #define SL_ALLOWCOMPRESS 0
  122. #endif
  123. #ifndef SL_NOICMP
  124. #define SL_NOICMP 0
  125. #endif
  126. int sl_docompress = SL_DOCOMPRESS;
  127. int sl_allowcompress = SL_ALLOWCOMPRESS;
  128. int sl_noicmp = SL_NOICMP;
  129.  
  130. /*
  131.  * SLMTU is a hard limit on input packet size.  To simplify the code
  132.  * and improve performance, we require that packets fit in an mbuf
  133.  * cluster, that there be enough extra room for the ifnet pointer that
  134.  * IP input requires and, if we get a compressed packet, there's
  135.  * enough extra room to expand the header into a max length tcp/ip
  136.  * header (128 bytes).  So, SLMTU can be at most
  137.  *    MCLBYTES - sizeof(struct ifnet *) - 128
  138.  *
  139.  * To insure we get good interactive response, the MTU wants to be
  140.  * the smallest size that amortizes the header cost.  (Remember
  141.  * that even with type-of-service queuing, we have to wait for any
  142.  * in-progress packet to finish.  I.e., we wait, on the average,
  143.  * 1/2 * mtu / cps, where cps is the line speed in characters per
  144.  * second.  E.g., 533ms wait for a 1024 byte MTU on a 9600 baud
  145.  * line.  The average compressed header size is 6-8 bytes so any
  146.  * MTU > 90 bytes will give us 90% of the line bandwidth.  A 100ms
  147.  * wait is tolerable (500ms is not), so want an MTU around 256.
  148.  * (Since TCP will send 212 byte segments (to allow for 40 byte
  149.  * headers), the typical packet size on the wire will be around 220
  150.  * bytes).  In 4.3tahoe+ systems, we can set an MTU in a route
  151.  * so we do that & leave the interface MTU relatively high (so we
  152.  * don't IP fragment when acting as a gateway to someone using a
  153.  * stupid MTU).
  154.  *
  155.  * Similar considerations apply to SLIP_HIWAT:  It's the amount of
  156.  * data that will be queued 'downstream' of us (i.e., in clists
  157.  * waiting to be picked up by the tty output interrupt).  If we
  158.  * queue a lot of data downstream, it's immune to our t.o.s. queuing.
  159.  * E.g., if SLIP_HIWAT is 1024, the interactive traffic in mixed
  160.  * telnet/ftp will see a 1 sec wait, independent of the mtu (the
  161.  * wait is dependent on the ftp window size but that's typically
  162.  * 1k - 4k).  So, we want SLIP_HIWAT just big enough to amortize
  163.  * the cost (in idle time on the wire) of the tty driver running
  164.  * off the end of its clists & having to call back slstart for a
  165.  * new packet.  For a tty interface with any buffering at all, this
  166.  * cost will be zero.  Even with a totally brain dead interface (like
  167.  * the one on a typical workstation), the cost will be <= 1 character
  168.  * time.  So, setting SLIP_HIWAT to ~100 guarantees that we'll lose
  169.  * at most 1% while maintaining good interactive response.
  170.  */
  171. #define    SLMTU    576
  172. #if NBPFILTER > 0
  173. #define BUFOFFSET (128+sizeof(struct ifnet **)+SLIP_HDRLEN)
  174. #else
  175. #define BUFOFFSET (128+sizeof(struct ifnet **))
  176. #endif
  177. #define    SLIP_HIWAT    roundup(50,CBSIZE)
  178. #define    CLISTRESERVE    1024    /* Can't let clists get too low */
  179.  
  180. /*
  181.  * The following disgusting hack gets around the problem that IP TOS
  182.  * can't be set in BSD/Sun OS yet.  We want to put "interactive"
  183.  * traffic on a high priority queue.  To decide if traffic is
  184.  * interactive, we check that a) it is TCP and b) one of it's ports
  185.  * if telnet, login, klogin, eklogin or ftp control.
  186.  */
  187. static u_short interactive_ports[16] = {
  188.     0,    513,    0,    0,    0,    21,    0,    23,
  189.     0,    2105,    0,    0,    0,    0,    0,    543
  190. };
  191. #define INTERACTIVE(p) (interactive_ports[(p) & 0xf] == (p))
  192.  
  193. struct sl_softc sl_softc[NSL];
  194.  
  195. #define FRAME_END        0xc0        /* Frame End */
  196. #define FRAME_ESCAPE        0xdb        /* Frame Esc */
  197. #define TRANS_FRAME_END        0xdc        /* transposed frame end */
  198. #define TRANS_FRAME_ESCAPE    0xdd        /* transposed frame esc */
  199.  
  200. #ifdef sun
  201. #define t_sc t_linep
  202. #else
  203. #define t_sc T_LINEP
  204. #endif
  205.  
  206. #if defined(SL_NIT) && defined(NIT)
  207. #include "../h/time.h"
  208. #include "../net/nit.h"
  209. #include "../netinet/if_ether.h"
  210. extern struct nit_cb nitcb;
  211. int sl_donit = 0;
  212. #endif
  213.  
  214. /* Compatibility with 4.2 BSD (and variants) */
  215. #ifndef MCLBYTES
  216. #define MCLBYTES CLBYTES
  217. #endif
  218. /* Sun OS3.x doesn't have an MCLGET or MCLFREE.  Sun OS4.x doesn't
  219.  * have an MCLFREE.  The code below should work on either Sun OS
  220.  * (this driver, however will *NOT* work on a stock Sun OS4 system
  221.  * because of the slow, broken, worthless, System-V "streams" tty
  222.  * driver).
  223.  *
  224.  * All BSD systems since 4.1c have both MCLGET and MCLFREE.
  225.  * However 4.2bsd had a second, unused parameter to MCLGET.  Some
  226.  * versions of cpp may complain if you compile this routine under
  227.  * a stock 4.2bsd.  For reasons I have never understood, various
  228.  * vendors chose to break BSD in mysterious ways (e.g., DEC's Ultrix
  229.  * changed the definition of m_off to make mbuf cluster use
  230.  * a factor of two more costly -- no doubt this was done to encourage
  231.  * the sale of faster processors since there is no technical
  232.  * justification whatsoever for the change).  If you are stuck with
  233.  * one of these abortions and, for reasons best known to yourself,
  234.  * don't want to upgrade to the BSD network code freely available via
  235.  * anonymous ftp from ucbarpa.berkeley.edu, the following macros
  236.  * might give you a prototype to work from.  Then again, they might
  237.  * not.  Good luck.
  238.  */
  239. #ifdef sun
  240. #ifndef MCLGET
  241. #define MCLGET(m) { int ms = splimp(); (void)mclget(m); (void) splx(ms); }
  242. #endif
  243. #ifndef MCLFREE
  244. #define    MCLFREE(p) { \
  245.     extern char *mclrefcnt; \
  246.     struct mbuf mxxx; \
  247.     mxxx.m_len = MCLBYTES; \
  248.     mxxx.m_off = (int)p - (int)xm; \
  249.     mxxx.m_cltype = 1; \
  250.     mclput(&mxxx); \
  251.     }
  252. #endif
  253. #endif
  254.  
  255. int sloutput(), slioctl();
  256.  
  257. /*
  258.  * Called from boot code to establish sl interfaces.
  259.  */
  260. slattach()
  261. {
  262.     register struct sl_softc *sc;
  263.     register int i = 0;
  264.  
  265.     if (sl_softc[0].sc_if.if_name == NULL) {
  266.         for (sc = sl_softc; i < NSL; sc++) {
  267.             sc->sc_if.if_name = "sl";
  268.             sc->sc_if.if_unit = i++;
  269.             sc->sc_if.if_mtu = SLMTU;
  270.             sc->sc_if.if_flags = IFF_POINTOPOINT;
  271.             sc->sc_if.if_ioctl = slioctl;
  272.             sc->sc_if.if_output = sloutput;
  273.             sc->sc_if.if_snd.ifq_maxlen = 50;
  274.             sc->sc_fastq.ifq_maxlen = 32;
  275.             if_attach(&sc->sc_if);
  276. #if NBPFILTER > 0
  277.             bpfattach(&sc->sc_bpf, &sc->sc_if, DLT_SLIP, 
  278.                   SLIP_HDRLEN);
  279. #endif
  280.         }
  281.     }
  282. }
  283.  
  284. static int
  285. slinit(sc)
  286.     register struct sl_softc *sc;
  287. {
  288.  
  289.     if (sc->sc_ep == (u_char *) 0) {
  290.         struct mbuf m;
  291.  
  292.         MCLGET((&m));
  293.         if (m.m_len == MCLBYTES)
  294.             sc->sc_ep = mtod(&m,u_char *) + (BUFOFFSET + SLMTU);
  295.         else {
  296.             printf("sl%d: can't allocate buffer\n", sc - sl_softc);
  297.             sc->sc_if.if_flags &= ~IFF_UP;
  298.             return (0);
  299.         }
  300.     }
  301.     sc->sc_buf = sc->sc_ep - SLMTU;
  302.     sc->sc_mp = sc->sc_buf;
  303.     if (sl_docompress)
  304.         sc->sc_if.if_flags |= IFF_LINK0;
  305.     else 
  306.         sc->sc_if.if_flags &=~ IFF_LINK0;
  307.     if (sl_allowcompress)
  308.         sc->sc_if.if_flags |= IFF_LINK1;
  309.     else 
  310.         sc->sc_if.if_flags &=~ IFF_LINK1;
  311.     if (sl_noicmp)
  312.         sc->sc_if.if_flags |= IFF_LINK2;
  313.     else 
  314.         sc->sc_if.if_flags &=~ IFF_LINK2;
  315.     sl_compress_init(&sc->sc_comp);
  316.     return (1);
  317. }
  318.  
  319. /*
  320.  * Line specific open routine.
  321.  * Attach the given tty to the first available sl unit.
  322.  */
  323. /* ARGSUSED */
  324. slopen(dev, tp)
  325.     dev_t dev;
  326.     register struct tty *tp;
  327. {
  328.     register struct sl_softc *sc;
  329.     register int nsl;
  330.  
  331.     if (!suser())
  332.         return (EPERM);
  333.     if (tp->t_line == SLIPDISC)
  334.         return (EBUSY);
  335.  
  336.     for (nsl = NSL, sc = sl_softc; --nsl >= 0; sc++)
  337.         if (sc->sc_ttyp == NULL) {
  338.             if (slinit(sc) == 0)
  339.                 return (ENOBUFS);
  340.             tp->t_sc = (caddr_t)sc;
  341.             sc->sc_ttyp = tp;
  342.             ttyflush(tp, FREAD | FWRITE);
  343.             return (0);
  344.         }
  345.     return (ENXIO);
  346. }
  347.  
  348. #ifdef sun
  349. /* XXX - Sun OS3 is missing these 4bsd routines.
  350.  *
  351.  * Mark an interface down and notify protocols of
  352.  * the transition.
  353.  */
  354. static void
  355. if_down(ifp)
  356.     register struct ifnet *ifp;
  357. {
  358.     register struct ifqueue *ifq = &ifp->if_snd;
  359.     register struct mbuf *m, *n;
  360.  
  361.     ifp->if_flags &=~ IFF_UP;
  362.     pfctlinput(PRC_IFDOWN, &ifp->if_addr);
  363.  
  364.     /* Flush the interface queue. */
  365.     n = ifq->ifq_head;
  366.     while (m = n) {
  367.         n = m->m_act;
  368.         m_freem(m);
  369.     }
  370.     ifq->ifq_head = 0;
  371.     ifq->ifq_tail = 0;
  372.     ifq->ifq_len = 0;
  373. }
  374.  
  375. static void
  376. if_rtdelete(ifp)
  377.     register struct ifnet *ifp;
  378. {
  379.     static struct rtentry route;
  380.  
  381.     if (ifp->if_flags & IFF_ROUTE) {
  382.         route.rt_dst = ifp->if_dstaddr;
  383.         route.rt_gateway = ifp->if_addr;
  384.         route.rt_flags = RTF_HOST|RTF_UP;
  385.         (void) rtrequest(SIOCDELRT, &route);
  386.         ifp->if_flags &=~ IFF_ROUTE;
  387.     }
  388. }
  389. #endif
  390.  
  391. /*
  392.  * Line specific close routine.
  393.  * Detach the tty from the sl unit.
  394.  * Mimics part of ttyclose().
  395.  */
  396. slclose(tp)
  397.     struct tty *tp;
  398. {
  399.     register struct sl_softc *sc;
  400.     int s;
  401.  
  402.     ttywflush(tp);
  403.     tp->t_line = 0;
  404.     s = splimp();
  405.     sc = (struct sl_softc *)tp->t_sc;
  406.     if (sc != NULL) {
  407. #ifdef sun
  408.         if_rtdelete(&sc->sc_if);
  409. #endif
  410.         if_down(&sc->sc_if);
  411.         sc->sc_ttyp = NULL;
  412.         tp->t_sc = NULL;
  413.         MCLFREE((struct mbuf *)(sc->sc_ep - (SLMTU + BUFOFFSET)));
  414.         sc->sc_ep = 0;
  415.         sc->sc_mp = 0;
  416.         sc->sc_buf = 0;
  417.     }
  418.     splx(s);
  419. }
  420.  
  421. /*
  422.  * Line specific (tty) ioctl routine.
  423.  * Provide a way to get the sl unit number.
  424.  */
  425. /* ARGSUSED */
  426. sltioctl(tp, cmd, data, flag)
  427.     struct tty *tp;
  428.     caddr_t data;
  429. {
  430.  
  431.     if (cmd == TIOCGETD) {
  432.         *(int *)data = ((struct sl_softc *)tp->t_sc)->sc_if.if_unit;
  433.         return (0);
  434.     }
  435.     return (-1);
  436. }
  437.  
  438. /*
  439.  * Queue a packet.  Start transmission if not active.
  440.  */
  441. sloutput(ifp, m, dst)
  442.     register struct ifnet *ifp;
  443.     register struct mbuf *m;
  444.     struct sockaddr *dst;
  445. {
  446.     register struct sl_softc *sc;
  447.     register struct ip *ip;
  448.     register struct ifqueue *ifq;
  449.     int s;
  450. #if NBPFILTER > 0
  451.     u_char bpfbuf[SLMTU + SLIP_HDRLEN];
  452.     register int len;
  453. #endif
  454.  
  455.     /*
  456.      * `Cannot happen' (see slioctl).  Someday we will extend
  457.      * the line protocol to support other address families.
  458.      */
  459.     if (dst->sa_family != AF_INET) {
  460.         printf("sl%d: af%d not supported\n", ifp->if_unit,
  461.             dst->sa_family);
  462.         m_freem(m);
  463.         return (EAFNOSUPPORT);
  464.     }
  465.  
  466.     sc = &sl_softc[ifp->if_unit];
  467.     if (sc->sc_ttyp == NULL) {
  468.         m_freem(m);
  469.         return (ENETDOWN);    /* sort of */
  470.     }
  471.     if ((sc->sc_ttyp->t_state & TS_CARR_ON) == 0) {
  472.         m_freem(m);
  473.         return (EHOSTUNREACH);
  474.     }
  475. #if NBPFILTER > 0
  476.     if (sc->sc_bpf) {
  477.         /*
  478.          * We need to save the TCP/IP header before it's compressed.
  479.          * To avoid complicated code, we just copy the entire packet
  480.          * into a stack buffer (since this is a serial line, packets
  481.          * should be short and/or the copy should be negligible cost
  482.          * compared to the packet transmission time).
  483.          */
  484.         register struct mbuf *m1 = m;
  485.         register u_char *cp = bpfbuf + SLIP_HDRLEN;
  486.         len = 0;
  487.         do {
  488.             register int mlen = m1->m_len;
  489.  
  490.             bcopy(mtod(m1, caddr_t), cp, mlen);
  491.             cp += mlen;
  492.             len += mlen;
  493.         } while (m1 = m1->m_next);
  494.     }
  495. #endif
  496.     ifq = &ifp->if_snd;
  497.     if ((ip = mtod(m, struct ip *))->ip_p == IPPROTO_TCP) {
  498.         register int p = ((int *)ip)[ip->ip_hl];
  499.  
  500.         if (INTERACTIVE(p & 0xffff) || INTERACTIVE(p >> 16)) {
  501.             ifq = &sc->sc_fastq;
  502.             p = 1;
  503.         } else
  504.             p = 0;
  505.  
  506.         if (sc->sc_if.if_flags & IFF_LINK0) {
  507.             /*
  508.              * The last parameter turns off connection id
  509.              * compression for background traffic:  Since
  510.              * fastq traffic can jump ahead of the background
  511.              * traffic, we don't know what order packets will
  512.              * go on the line.
  513.              */
  514.             p = sl_compress_tcp(m, ip, &sc->sc_comp, p);
  515.             *mtod(m, u_char *) |= p;
  516.         }
  517.     } else if ((sc->sc_if.if_flags & IFF_LINK2) &&
  518.         ip->ip_p == IPPROTO_ICMP) {
  519.         m_freem(m);
  520.         return (0);
  521.     }
  522. #if NBPFILTER > 0
  523.     if (sc->sc_bpf) {
  524.         /*
  525.          * Put the SLIP pseudo-"link header" in place.  The compressed
  526.          * header is now at the beginning of the mbuf.
  527.          */
  528.         bpfbuf[SLX_DIR] = SLIPDIR_OUT;
  529.         bcopy(mtod(m, caddr_t), &bpfbuf[SLX_CHDR], CHDR_LEN);
  530.         bpf_tap(sc->sc_bpf, bpfbuf, len + SLIP_HDRLEN);
  531.     }
  532. #endif
  533.     s = splimp();
  534.     if (IF_QFULL(ifq)) {
  535.         IF_DROP(ifq);
  536.         m_freem(m);
  537.         splx(s);
  538.         sc->sc_if.if_oerrors++;
  539.         return (ENOBUFS);
  540.     }
  541.     IF_ENQUEUE(ifq, m);
  542.     if (sc->sc_ttyp->t_outq.c_cc == 0)
  543.         slstart(sc->sc_ttyp);
  544.     splx(s);
  545.     return (0);
  546. }
  547.  
  548. /*
  549.  * Start output on interface.  Get another datagram
  550.  * to send from the interface queue and map it to
  551.  * the interface before starting output.
  552.  */
  553. slstart(tp)
  554.     register struct tty *tp;
  555. {
  556.     register struct sl_softc *sc = (struct sl_softc *)tp->t_sc;
  557.     register struct mbuf *m;
  558.     register u_char *cp;
  559.     int s;
  560.     struct mbuf *m2;
  561.     extern int cfreecount;
  562.  
  563.     for (;;) {
  564.         /*
  565.          * If there is more in the output queue, just send it now.
  566.          * We are being called in lieu of ttstart and must do what
  567.          * it would.
  568.          */
  569.         if (tp->t_outq.c_cc != 0) {
  570.             (*tp->t_oproc)(tp);
  571.             if (tp->t_outq.c_cc > SLIP_HIWAT)
  572.                 return;
  573.         }
  574.         /*
  575.          * This happens briefly when the line shuts down.
  576.          */
  577.         if (sc == NULL)
  578.             return;
  579.  
  580.         /*
  581.          * Get a packet and send it to the interface.
  582.          */
  583.         s = splimp();
  584.         IF_DEQUEUE(&sc->sc_fastq, m);
  585.         if (m == NULL)
  586.             IF_DEQUEUE(&sc->sc_if.if_snd, m);
  587. #if defined(SL_NIT) && defined(NIT)
  588.         if (m && sl_donit && nitcb.ncb_next != &nitcb) {
  589.             /* do nit processing if there's anyone listening */
  590.             static struct ether_header oheader = { { 1 }, { 2 } };
  591.             struct nit_ii nii;
  592.             int len = 0;
  593.  
  594.             m2 = m;
  595.             do {
  596.                 len += m2->m_len;
  597.             } while (m2 = m2->m_next);
  598.  
  599.             oheader.ether_type = *mtod(m, u_char *);
  600.             nii.nii_header = (caddr_t)&oheader;
  601.             nii.nii_hdrlen = sizeof(oheader);
  602.             nii.nii_type = oheader.ether_type;
  603.             nii.nii_datalen = len;
  604.             nii.nii_promisc = 0;
  605.             nit_tap(&sc->sc_if, m, &nii);
  606.         }
  607. #endif
  608.         splx(s);
  609.         if (m == NULL)
  610.             return;
  611.         /*
  612.          * If system is getting low on clists, just flush our
  613.          * output queue (if the stuff was important, it'll get
  614.          * retransmitted).
  615.          */
  616.         if (cfreecount < CLISTRESERVE + SLMTU) {
  617.             m_freem(m);
  618.             sc->sc_if.if_collisions++;
  619.             continue;
  620.         }
  621.  
  622.         /*
  623.          * The extra FRAME_END will start up a new packet, and thus
  624.          * will flush any accumulated garbage.  We do this whenever
  625.          * the line may have been idle for some time.
  626.          */
  627.         if (tp->t_outq.c_cc == 0) {
  628.             ++sc->sc_bytessent;
  629.             (void) putc(FRAME_END, &tp->t_outq);
  630.         }
  631.  
  632.         while (m) {
  633.             register u_char *ep;
  634.  
  635.             cp = mtod(m, u_char *); ep = cp + m->m_len;
  636.             while (cp < ep) {
  637.                 /*
  638.                  * Find out how many bytes in the string we can
  639.                  * handle without doing something special.
  640.                  */
  641.                 register u_char *bp = cp;
  642.  
  643.                 while (cp < ep) {
  644.                     switch (*cp++) {
  645.                     case FRAME_ESCAPE:
  646.                     case FRAME_END:
  647.                         --cp;
  648.                         goto out;
  649.                     }
  650.                 }
  651.                 out:
  652.                 if (cp > bp) {
  653.                     /*
  654.                      * Put n characters at once
  655.                      * into the tty output queue.
  656.                      */
  657.                     if (b_to_q((char *)bp, cp - bp, &tp->t_outq))
  658.                         break;
  659.                     sc->sc_bytessent += cp - bp;
  660.                 }
  661.                 /*
  662.                  * If there are characters left in the mbuf,
  663.                  * the first one must be special..
  664.                  * Put it out in a different form.
  665.                  */
  666.                 if (cp < ep) {
  667.                     if (putc(FRAME_ESCAPE, &tp->t_outq))
  668.                         break;
  669.                     if (putc(*cp++ == FRAME_ESCAPE ?
  670.                        TRANS_FRAME_ESCAPE : TRANS_FRAME_END,
  671.                        &tp->t_outq)) {
  672.                         (void) unputc(&tp->t_outq);
  673.                         break;
  674.                     }
  675.                     sc->sc_bytessent += 2;
  676.                 }
  677.             }
  678.             MFREE(m, m2);
  679.             m = m2;
  680.         }
  681.  
  682.         if (putc(FRAME_END, &tp->t_outq)) {
  683.             /*
  684.              * Not enough room.  Remove a char to make room
  685.              * and end the packet normally.
  686.              * If you get many collisions (more than one or two
  687.              * a day) you probably do not have enough clists
  688.              * and you should increase "nclist" in param.c.
  689.              */
  690.             (void) unputc(&tp->t_outq);
  691.             (void) putc(FRAME_END, &tp->t_outq);
  692.             sc->sc_if.if_collisions++;
  693.         } else {
  694.             ++sc->sc_bytessent;
  695.             sc->sc_if.if_opackets++;
  696.         }
  697.     }
  698. }
  699.  
  700. /*
  701.  * Copy data buffer to mbuf chain; add ifnet pointer.
  702.  */
  703. static struct mbuf *
  704. sl_btom(sc, len)
  705.     register struct sl_softc *sc;
  706.     register int len;
  707. {
  708.     register u_char *cp;
  709.     register struct mbuf *m;
  710.  
  711.     MGET(m, M_DONTWAIT, MT_DATA);
  712.     if (m == NULL)
  713.         return (NULL);
  714.  
  715.     /*
  716.      * If we have more than MLEN bytes, it's cheaper to
  717.      * queue the cluster we just filled & allocate a new one
  718.      * for the input buffer.  Otherwise, fill the mbuf we
  719.      * allocated above.  Note that code in the input routine
  720.      * guarantees that packet + ifp will fit in a cluster and
  721.      * initial setup left room for interface pointer.
  722.      */
  723.     cp = sc->sc_buf;
  724. #if BSD==43
  725.     if (len >= MLEN - sizeof(struct ifnet *)) {
  726.         MCLGET(m);
  727.         if (m->m_len != MCLBYTES) {
  728.             /* we couldn't get a cluster - if memory's this
  729.              * low, it's time to start dropping packets. */
  730.             m_freem(m);
  731.             return (NULL);
  732.         }
  733.         sc->sc_ep = mtod(m, u_char *) + (BUFOFFSET + SLMTU);
  734.         m->m_off = (int)cp - (int)m - sizeof(struct ifnet *);
  735.     } else {
  736.         bcopy((caddr_t)cp, mtod(m, caddr_t) + sizeof(struct ifnet *),
  737.             len);
  738.     }
  739.     m->m_len = len + sizeof(struct ifnet *);
  740.     *mtod(m, struct ifnet **) = &sc->sc_if;
  741. #else
  742.     if (len >= MLEN) {
  743.         MCLGET(m);
  744.         if (m->m_len != MCLBYTES) {
  745.             /* we couldn't get a cluster - if memory's this
  746.              * low, it's time to start dropping packets. */
  747.             m_freem(m);
  748.             return (NULL);
  749.         }
  750.         sc->sc_ep = mtod(m, u_char *) + (BUFOFFSET + SLMTU);
  751.         m->m_off = (int)cp - (int)m;
  752.     } else {
  753.         bcopy((caddr_t)cp, mtod(m, caddr_t), len);
  754.     }
  755.     m->m_len = len;
  756. #endif
  757.     return (m);
  758. }
  759.  
  760. /*
  761.  * tty interface receiver interrupt.
  762.  */
  763. slinput(c, tp)
  764.     register int c;
  765.     register struct tty *tp;
  766. {
  767.     register struct sl_softc *sc;
  768.     register struct mbuf *m;
  769.     register int len;
  770.     int s;
  771. #if NBPFILTER > 0
  772.     u_char chdr[CHDR_LEN];
  773. #endif
  774.     tk_nin++;
  775.     sc = (struct sl_softc *)tp->t_sc;
  776.     if (sc == NULL)
  777.         return;
  778.  
  779.     ++sc->sc_bytesrcvd;
  780.     c &= 0xff;
  781.     switch (c) {
  782.  
  783.     case TRANS_FRAME_ESCAPE:
  784.         if (sc->sc_escape)
  785.             c = FRAME_ESCAPE;
  786.         break;
  787.  
  788.     case TRANS_FRAME_END:
  789.         if (sc->sc_escape)
  790.             c = FRAME_END;
  791.         break;
  792.  
  793.     case FRAME_ESCAPE:
  794.         sc->sc_escape = 1;
  795.         return;
  796.  
  797.     case FRAME_END:
  798.         len = sc->sc_mp - sc->sc_buf;
  799.         if (len < 3)
  800.             /* less than min length packet - ignore */
  801.             goto newpack;
  802.  
  803. #if defined(SL_NIT) && defined(NIT)
  804.         if (sl_donit && nitcb.ncb_next != &nitcb) {
  805.             /* do nit processing if there's anyone listening */
  806.             static struct ether_header iheader = { { 2 }, { 1 } };
  807.             static struct mbuf mb;
  808.             struct nit_ii nii;
  809.  
  810.             m = &mb;
  811.             m->m_len = len;
  812.             m->m_off = (int)sc->sc_buf - (int)m;
  813.             iheader.ether_type = *sc->sc_buf;
  814.             nii.nii_header = (caddr_t)&iheader;
  815.             nii.nii_hdrlen = sizeof(iheader);
  816.             nii.nii_type = iheader.ether_type;
  817.             nii.nii_datalen = len;
  818.             nii.nii_promisc = 0;
  819.             nit_tap(&sc->sc_if, m, &nii);
  820.         }
  821. #endif
  822. #if NBPFILTER > 0
  823.         if (sc->sc_bpf)
  824.             /*
  825.              * Save the compressed header, so we can
  826.              * tack it on later.  Note that we just
  827.              * we will end up copying garbage in some
  828.              * cases but this is okay.  We remember
  829.              * where the buffer started so we can
  830.              * compute the new header length.
  831.              */
  832.             bcopy(sc->sc_buf, chdr, CHDR_LEN);
  833. #endif
  834.         if ((c = (*sc->sc_buf & 0xf0)) != (IPVERSION << 4)) {
  835.             if (c & 0x80)
  836.                 c = TYPE_COMPRESSED_TCP;
  837.             else if (c == TYPE_UNCOMPRESSED_TCP)
  838.                 *sc->sc_buf &= 0x4f;
  839.             /*
  840.              * we've got something that's not an IP packet.
  841.              * If compression is enabled, try to uncompress it.
  842.              * Otherwise, if `auto-enable' compression is on and
  843.              * it's a reasonable packet, uncompress it then
  844.              * enable compression.  Otherwise, drop it.
  845.              */
  846.             if (sc->sc_if.if_flags & IFF_LINK0) {
  847.                 len = sl_uncompress_tcp(&sc->sc_buf, len,
  848.                             (u_int)c, &sc->sc_comp);
  849.                 if (len <= 0)
  850.                     goto error;
  851.             } else if ((sc->sc_if.if_flags & IFF_LINK1) &&
  852.                    c == TYPE_UNCOMPRESSED_TCP && len >= 40) {
  853.                 len = sl_uncompress_tcp(&sc->sc_buf, len,
  854.                             (u_int)c, &sc->sc_comp);
  855.                 if (len <= 0)
  856.                     goto error;
  857.                 sc->sc_if.if_flags |= IFF_LINK0;
  858.             } else
  859.                 goto error;
  860.         }
  861. #if NBPFILTER > 0
  862.         if (sc->sc_bpf) {
  863.             /*
  864.              * Put the SLIP pseudo-"link header" in place.
  865.              * We couldn't do this any earlier since
  866.              * decompression probably moved the buffer
  867.              * pointer.  Then, invoke BPF.
  868.              */
  869.             register u_char *hp = sc->sc_buf - SLIP_HDRLEN;
  870.  
  871.             hp[SLX_DIR] = SLIPDIR_IN;
  872.             bcopy(chdr, &hp[SLX_CHDR], CHDR_LEN);
  873.             bpf_tap(sc->sc_bpf, hp, len + SLIP_HDRLEN);
  874.         }
  875. #endif
  876.         m = sl_btom(sc, len);
  877.         if (m == NULL)
  878.             goto error;
  879.  
  880.         sc->sc_if.if_ipackets++;
  881.         s = splimp();
  882.         if (IF_QFULL(&ipintrq)) {
  883.             IF_DROP(&ipintrq);
  884.             sc->sc_if.if_ierrors++;
  885.             m_freem(m);
  886.         } else {
  887.             IF_ENQUEUE(&ipintrq, m);
  888.             schednetisr(NETISR_IP);
  889.         }
  890.         splx(s);
  891.         goto newpack;
  892.     }
  893.     if (sc->sc_mp < sc->sc_ep) {
  894.         *sc->sc_mp++ = c;
  895.         sc->sc_escape = 0;
  896.         return;
  897.     }
  898. error:
  899.     sc->sc_if.if_ierrors++;
  900. newpack:
  901.     sc->sc_mp = sc->sc_buf = sc->sc_ep - SLMTU;
  902.     sc->sc_escape = 0;
  903. }
  904.  
  905. /*
  906.  * Process an ioctl request.
  907.  */
  908. slioctl(ifp, cmd, data)
  909.     register struct ifnet *ifp;
  910.     int cmd;
  911.     caddr_t data;
  912. {
  913.     int s = splimp(), error = 0;
  914. #ifndef sun
  915.     register struct ifaddr *ifa = (struct ifaddr *)data;
  916.  
  917.     switch (cmd) {
  918.  
  919.     case SIOCSIFADDR:
  920.         if (ifa->ifa_addr.sa_family == AF_INET)
  921.             ifp->if_flags |= IFF_UP;
  922.         else
  923.             error = EAFNOSUPPORT;
  924.         break;
  925.  
  926.     case SIOCSIFDSTADDR:
  927.         if (ifa->ifa_addr.sa_family != AF_INET)
  928.             error = EAFNOSUPPORT;
  929.         break;
  930.  
  931.     default:
  932.         error = EINVAL;
  933.     }
  934. #else
  935.     switch (cmd) {
  936.     case SIOCSIFADDR:
  937. #ifdef LBL
  938.         {
  939.         register u_long addr;
  940.  
  941.         if_rtdelete(ifp);
  942.         ifp->if_addr = *(struct sockaddr *)data;
  943.         addr = ((struct sockaddr_in *)data)->sin_addr.s_addr;
  944.         if (IN_CLASSA(addr))
  945.             ifp->if_netmask = IN_CLASSA_NET;
  946.         else if (IN_CLASSB(addr))
  947.             ifp->if_netmask = IN_CLASSB_NET;
  948.         else
  949.             ifp->if_netmask = IN_CLASSC_NET;
  950.         ifp->if_net = addr & ifp->if_netmask;
  951.         ifp->if_host[0] = addr &~ ifp->if_netmask;
  952.         ifp->if_subnetmask |= ifp->if_netmask;
  953.         ifp->if_subnet = addr & ifp->if_subnetmask;
  954.         ifp->if_flags |= IFF_UP|IFF_RUNNING;
  955.         ifp->if_flags &=~ IFF_BROADCAST;
  956.         /* set up routing table entry */
  957.         error = rtinit(&ifp->if_dstaddr, &ifp->if_addr,
  958.                 RTF_HOST|RTF_UP);
  959.         ifp->if_flags |= IFF_ROUTE;
  960.         }
  961. #else
  962.         if_rtdelete(ifp);
  963.         ifp->if_addr = *(struct sockaddr *)data;
  964.         ifp->if_net = in_netof(((struct sockaddr_in *)data)->sin_addr);
  965.         ifp->if_flags |= IFF_UP|IFF_RUNNING;
  966.         ifp->if_flags &=~ IFF_BROADCAST;
  967.         /* set up routing table entry */
  968.         error = rtinit(&ifp->if_dstaddr, &ifp->if_addr,
  969.                 RTF_HOST|RTF_UP);
  970.         ifp->if_flags |= IFF_ROUTE;
  971. #endif
  972.         break;
  973.  
  974.     case SIOCSIFDSTADDR:
  975.         /* all the real work is done for us in ../net/if.c */
  976.         break;
  977.  
  978.     default:
  979.         error = EINVAL;
  980.     }
  981. #endif
  982.     splx(s);
  983.     return (error);
  984. }
  985. #endif
  986.